/**
 * @file memm2.c
 * 格式化的内存管理。通过位查询的办法，使内存申请速度更快；用双向链免去在释放时通过遍历链来找到可合并的空闲块
 * 可使用偏移量代替指针，即内存的地址允许被迁移并继续管理
 * 可自由指定堆位置
 * 更快速，速度稳定
 * 释放内存时带有效性判断
 * 可一次性全部释放内存
 * 允许从尾部开始申请内存
 * 使用从最小内存块分配策略
 *
 * @author lokliang
 * @brief
 * @version 0.2
 * @date 2022-12-07
 * @date 2022-01-14
 *
 * @copyright Copyright (c) 2022
 *
 */

#if defined(CONFIG_MEMM_TYPE) && (CONFIG_MEMM_TYPE == 2)

#include "memm.h"
#include "sys_log.h"

#ifndef NULL
#define NULL ((void *)0)
#endif

#ifndef CONFIG_MEMM_NODE_TYPE
#define CONFIG_MEMM_NODE_TYPE 0 /* 0 使用指针连结（推荐）；1 使用偏移量连结，内存的地址允许被迁移并继续管理 */
#endif

#if CONFIG_MEMM_NODE_TYPE == 1

typedef struct
{
    signed next;         // 指向下一个已使用的内存块的管理地址
    unsigned space_size; // 整个块的大小（包含本结构体和尾段的指针）
} memm_node_handle_t;    // 已申请内存和空闲内存的共用结构，放在整个结构的开始处

typedef signed memm_node_t;

#else /* #if CONFIG_MEMM_NODE_TYPE == 1 */

typedef struct
{
    void *next;          // 指向下一个已使用的内存块的管理地址
    unsigned space_size; // 整个块的大小（包含本结构体和尾段的指针）
} memm_node_handle_t;    // 已申请内存和空闲内存的共用结构，放在整个结构的开始处

typedef memm_node_handle_t *memm_node_t;

#endif /* #if CONFIG_MEMM_NODE_TYPE == 1 */

typedef struct
{
    memm_node_t prev;
} memm_tail_active_t; // 已申请内存的数据结构，放在整个结构的结尾处

typedef struct
{
    memm_node_t self;
    memm_node_t prev;
} memm_tail_free_t; // 空闲内存的数据结构，放在整个结构的结尾处

typedef struct
{
    memm_node_t start; // 用户定义的内存的基地址
    memm_node_t end;   // 用户定义的内存的结束地址

    unsigned free_total; // 统计总空闲数（包含所有碎片）

    unsigned bm_free;
    memm_node_t free_node[8 * sizeof(int)];

} memm_handle_t;

#define _MEMM_BLOCK_MANAGER_SPACE (sizeof(memm_node_handle_t) + sizeof(memm_tail_active_t)) // 每个管理块额外消耗的字节数

#define _MEMM_FREE_TAB_NUMS (sizeof(p_hdr->free_node) / sizeof(p_hdr->free_node[0]))
#define _MEMM_BLOCK_DATA_TAIL_Struct(BLOCK, SIZE) (memm_tail_active_t *)&((uint8_t *)(BLOCK))[SIZE - sizeof(memm_tail_active_t)]
#define _MEMM_BLOCK_FREE_TAIL_Struct(BLOCK, SIZE) (memm_tail_free_t *)&((uint8_t *)(BLOCK))[SIZE - sizeof(memm_tail_free_t)]
#define _MEMM_DATA_VALID (memm_node_t)0x87654321 // 标记所申请的内存有效

/************************************************************************************************/

#if CONFIG_MEMM_NODE_TYPE == 1
#define _MEMM_GET_POINTER(DEV) ((memm_node_handle_t *)(&((uint8_t *)p_hdr)[DEV]))
#define _MEMM_GET_DEV_VALUE(P) ((size_t)(P) - (size_t)p_hdr)
#else
#define _MEMM_GET_POINTER(DEV) (DEV)
#define _MEMM_GET_DEV_VALUE(P) (P)
#endif

static void *_memm_malloc(memm_t *hdl, size_t size, signed tail);
static void *_memm_calloc(memm_t *hdl, size_t size, signed tail);
static void *_memm_realloc(memm_t *hdl, void *p, size_t newsize);
static void *_memm_link_alloc(memm_handle_t *p_hdr, memm_node_handle_t *p_free_block, size_t block_space, size_t alloc_space, signed tail);

static void _memm_link_free_insert(memm_handle_t *p_hdr, memm_node_handle_t *p_free_block, size_t space_size);
static void _memm_link_free_remove(memm_handle_t *p_hdr, memm_node_handle_t *p_free_block);

memm_t *memm_init(void *mem_base, size_t mem_size)
{
    memm_handle_t *p_hdr = (memm_handle_t *)mem_base;
    memm_node_t start = (memm_node_t)_MEMM_GET_DEV_VALUE(&p_hdr[1]);
    memm_node_t end = (memm_node_t)((((size_t)start) + mem_size - sizeof(memm_handle_t)) / sizeof(size_t) * sizeof(size_t));

    /* 使用内存对齐 */
    start = (memm_node_t)(((size_t)start + sizeof(size_t) - 1) / sizeof(size_t) * sizeof(size_t));
    end = (memm_node_t)(((size_t)start + mem_size - sizeof(memm_handle_t)) / sizeof(size_t) * sizeof(size_t));
    mem_size = (size_t)end - (size_t)start;

    /* 检查参数 */
    if (mem_size < _MEMM_BLOCK_MANAGER_SPACE + sizeof(size_t))
    {
        SYS_LOG_WRN("Insufficient Space, header: %d bytes, block: %d bytes",
                    sizeof(memm_handle_t),
                    _MEMM_BLOCK_MANAGER_SPACE + sizeof(size_t));
        return NULL;
    }

    p_hdr->start = start;
    p_hdr->end = end;

    memm_free_all((memm_t *)p_hdr);

    return (memm_t *)p_hdr;
}

/**
 * @brief
 *
 * @param hdl
 * @param size
 * @return void* 0 -- 内存不足, != NULL -- 申请到的空间地址
 */
void *memm_malloc(memm_t *hdl, size_t size)
{
    return _memm_malloc(hdl, size, 0);
}

void *memm_calloc(memm_t *hdl, size_t size)
{
    return _memm_calloc(hdl, size, 0);
}

void *memm_malloc_tail(memm_t *hdl, size_t size)
{
    return _memm_malloc(hdl, size, 1);
}

void *memm_realloc(memm_t *hdl, void *p, size_t newsize)
{
    if (p == NULL)
    {
        return _memm_malloc(hdl, newsize, 0);
    }
    else
    {
        return _memm_realloc(hdl, p, newsize);
    }
}

int memm_free(memm_t *hdl, void *p)
{
    if (hdl == NULL || p == NULL)
    {
        return -1;
    }
    else
    {
#if (CONFIG_SYS_LOG_WRN_ON == 1)
        if (memm_is_valid(hdl, p) == false)
        {
            SYS_LOG_WRN("Memory attribute error: %p", p);
            return -1;
        }
#endif /* #if (CONFIG_SYS_LOG_WRN_ON == 1) */

        memm_handle_t *p_hdr = (memm_handle_t *)hdl;
        memm_node_handle_t *p_cur_free_block = &((memm_node_handle_t *)p)[-1];
        size_t space_size = p_cur_free_block->space_size;
        memm_node_handle_t *p_next_free_block = (memm_node_handle_t *)&((uint8_t *)p_cur_free_block)[space_size];

        /* 合并前一个空闲块 */
        if ((size_t)p_cur_free_block > (size_t)_MEMM_GET_POINTER(p_hdr->start)) // 当前内存块不是在最底端
        {
            memm_tail_active_t *p_prev_tail_struce_data = &((memm_tail_active_t *)p_cur_free_block)[-1];

            if (p_prev_tail_struce_data->prev != _MEMM_DATA_VALID) // 与前一个相邻的块是空闲块
            {
                memm_tail_free_t *p_prev_tail_struct_free = &((memm_tail_free_t *)p_cur_free_block)[-1];
                memm_node_handle_t *p_prev_free_block = _MEMM_GET_POINTER(p_prev_tail_struct_free->self);

                /* 更新信息 */
                space_size += p_prev_free_block->space_size;
                p_cur_free_block = p_prev_free_block;

                /* 删除空闲块链接 */
                _memm_link_free_remove(p_hdr, p_prev_free_block);
            }
        }

        /* 合并后一个空闲块 */
        if ((size_t)p_next_free_block < (size_t)_MEMM_GET_POINTER(p_hdr->end)) // 当前内存块不是在最顶端
        {
            if (p_next_free_block->next != _MEMM_DATA_VALID) // 与后一个相邻的块是空闲块
            {
                /* 更新信息 */
                space_size += p_next_free_block->space_size;

                /* 删除空闲块链接 */
                _memm_link_free_remove(p_hdr, p_next_free_block);
            }
        }

        /* 重新链接空闲块 */
        _memm_link_free_insert(p_hdr, p_cur_free_block, space_size);

        return 0;
    }
}

void memm_free_all(memm_t *hdl)
{
    memm_handle_t *p_hdr = (memm_handle_t *)hdl;
    memm_node_t start = p_hdr->start; // 用户定义的内存的基地址
    memm_node_t end = p_hdr->end;     // 用户定义的内存的结束地址

    /* 初始化 *p_hdr */
    memset(p_hdr, 0, sizeof(*p_hdr));
    p_hdr->start = start;
    p_hdr->end = end;

    _memm_link_free_insert(p_hdr, _MEMM_GET_POINTER(start), (size_t)end - (size_t)start);
}

size_t memm_used_size(memm_t *hdl)
{
    memm_handle_t *p_hdr = (memm_handle_t *)hdl;

    return ((size_t)p_hdr->end - (size_t)p_hdr->start - _MEMM_BLOCK_MANAGER_SPACE - p_hdr->free_total);
}

size_t memm_free_size(memm_t *hdl)
{
    memm_handle_t *p_hdr = (memm_handle_t *)hdl;
    return p_hdr->free_total;
}

size_t memm_block_max(memm_t *hdl)
{
    memm_handle_t *p_hdr = (memm_handle_t *)hdl;
    size_t bit_mask_max;

    /* 简单搜索最大内存所在段 */
    for (bit_mask_max = 0; (p_hdr->bm_free >> bit_mask_max & 1) == 0 && bit_mask_max < _MEMM_FREE_TAB_NUMS; bit_mask_max++)
    {
    }
    if (bit_mask_max < _MEMM_FREE_TAB_NUMS)
    {
        memm_node_handle_t *p_first_block = _MEMM_GET_POINTER(p_hdr->free_node[_MEMM_FREE_TAB_NUMS - 1 - bit_mask_max]);
        memm_node_handle_t *p_test_block = p_first_block;
        size_t ret = 0;

        do
        {
            if (ret < p_test_block->space_size)
            {
                ret = p_test_block->space_size;
            }
            p_test_block = _MEMM_GET_POINTER(p_test_block->next);
        } while (p_test_block != p_first_block);

        return ret - _MEMM_BLOCK_MANAGER_SPACE;
    }
    else
    {
        return 0;
    }
}

bool memm_is_valid(memm_t *hdl, void *p)
{
    if (hdl == NULL || p == NULL)
    {
        return false;
    }
    else
    {
        memm_handle_t *p_hdr = (memm_handle_t *)hdl;
        memm_node_handle_t *p_data_block = &((memm_node_handle_t *)p)[-1];
        memm_tail_active_t *p_data_block_tail = _MEMM_BLOCK_DATA_TAIL_Struct(p_data_block, p_data_block->space_size);

        if ((size_t)p_data_block < (size_t)_MEMM_GET_POINTER(p_hdr->start) ||
            (size_t)p_data_block > (size_t)_MEMM_GET_POINTER(p_hdr->end) - (_MEMM_BLOCK_MANAGER_SPACE + sizeof(memm_tail_active_t)) ||
            p_data_block->next != _MEMM_DATA_VALID ||
            p_data_block_tail->prev != _MEMM_DATA_VALID)
        {
            return false;
        }
    }
    return true;
}

size_t memm_get_header_info_size(void)
{
    return sizeof(memm_handle_t);
}

size_t memm_get_block_info_size(void)
{
    return _MEMM_BLOCK_MANAGER_SPACE;
}

size_t memm_get_data_space_size(void *p)
{
    return ((&((memm_node_handle_t *)(p))[-1])->space_size - _MEMM_BLOCK_MANAGER_SPACE);
}

void *memm_get_base(memm_t *hdl)
{
    memm_handle_t *p_hdr = (memm_handle_t *)hdl;
    return _MEMM_GET_POINTER(p_hdr->start);
}

void *memm_get_end(memm_t *hdl)
{
    memm_handle_t *p_hdr = (memm_handle_t *)hdl;
    return _MEMM_GET_POINTER(p_hdr->end);
}

static void *_memm_malloc(memm_t *hdl, size_t size, signed tail)
{
    memm_handle_t *p_hdr = (memm_handle_t *)hdl;
    memm_node_handle_t *p_free_hdr;
    memm_node_handle_t *p_free_block;
    size_t bm_free = p_hdr->bm_free;
    size_t bit_mask_free;
    size_t bit_mask_alloc;
    size_t alloc_space;

    if (size < sizeof(memm_tail_free_t) - sizeof(memm_tail_active_t))
    {
        size = sizeof(memm_tail_free_t) - sizeof(memm_tail_active_t);
    }

    // 确定真正需要分配的大小
    alloc_space = (size + _MEMM_BLOCK_MANAGER_SPACE + (sizeof(size_t) - 1)) / sizeof(size_t) * sizeof(size_t); // 空间大小对齐

    /* 计算申请空间大小的有效位数 */
    bit_mask_alloc = _MEMM_FREE_TAB_NUMS - _cpu_clz(alloc_space);

    if (tail == 0)
    {
        /* 从相同容量等级的空闲块链中链搜索 */
        bit_mask_free = _cpu_clz(bm_free & 0xFFFFFFFF >> (bit_mask_alloc - 1));
        if (bit_mask_free < _MEMM_FREE_TAB_NUMS) // 有可用的空闲空间
        {
            size_t max_space = ~0;
            memm_node_handle_t *p_best_block = NULL;

            p_free_hdr = _MEMM_GET_POINTER(p_hdr->free_node[bit_mask_free]);
            p_free_block = p_free_hdr;

            do
            {
                if (p_free_block->space_size >= alloc_space)
                {
                    if (max_space > p_free_block->space_size)
                    {
                        max_space = p_free_block->space_size;
                        p_best_block = p_free_block;
                        if (alloc_space == p_free_block->space_size)
                        {
                            break;
                        }
                    }
                }
                p_free_block = _MEMM_GET_POINTER(p_free_block->next);

            } while (p_free_block != p_free_hdr);

            if (p_best_block != NULL)
            {
                _memm_link_free_remove(p_hdr, p_best_block); /* 从空闲链移出 */
                return _memm_link_alloc(p_hdr, p_best_block, p_best_block->space_size, alloc_space, 0);
            }
        }

        /* 直接在大一级的空闲链中申请 */
        bit_mask_free = _cpu_clz(bm_free & 0xFFFFFFFF >> (bit_mask_alloc - 0));
        if (bit_mask_free < _MEMM_FREE_TAB_NUMS) // 有可用的空闲空间
        {
            p_free_block = _MEMM_GET_POINTER(p_hdr->free_node[bit_mask_free]);
            _memm_link_free_remove(p_hdr, p_free_block); /* 从空闲链移出 */
            return _memm_link_alloc(p_hdr, p_free_block, p_free_block->space_size, alloc_space, 0);
        }
    }
    else // tial != NULL
    {
        memm_node_handle_t *p_match_block = NULL;

        /* 搜索靠后的可用内存所在段 */
        for (bit_mask_free = _cpu_clz(bm_free & 0xFFFFFFFF >> (bit_mask_alloc - 1));
             bit_mask_free < _MEMM_FREE_TAB_NUMS;
             bit_mask_free = _cpu_clz(bm_free & 0xFFFFFFFF >> (bit_mask_free + 1)))
        {
            p_free_hdr = _MEMM_GET_POINTER(p_hdr->free_node[bit_mask_free]);
            p_free_block = p_free_hdr;

            do
            {
                if (p_free_block->space_size >= alloc_space)
                {
                    if (p_match_block < p_free_block)
                    {
                        p_match_block = p_free_block;
                    }
                }

                p_free_block = _MEMM_GET_POINTER(p_free_block->next);

            } while (p_free_block != p_free_hdr);
        }

        if (p_match_block != NULL)
        {
            _memm_link_free_remove(p_hdr, p_match_block); /* 从空闲链移出 */
            return _memm_link_alloc(p_hdr, p_match_block, p_match_block->space_size, alloc_space, 1);
        }
    }

    return NULL;
}

static void *_memm_calloc(memm_t *hdl, size_t size, signed tail)
{
    void *ret;

    ret = _memm_malloc(hdl, size, tail);
    if (ret == NULL)
    {
        return NULL;
    }

    memset(ret, 0, size);

    return ret;
}

static void *_memm_realloc(memm_t *hdl, void *p, size_t newsize)
{
#if (CONFIG_SYS_LOG_WRN_ON == 1)
    if (memm_is_valid(hdl, p) == false)
    {
        SYS_LOG_WRN("Memory attribute error: %p", p);
        return NULL;
    }
#endif /* #if (CONFIG_SYS_LOG_WRN_ON == 1) */

    if (p == NULL)
    {
        return memm_malloc(hdl, newsize);
    }

    if (newsize == 0)
    {
        memm_free(hdl, p);
        return NULL;
    }

    memm_handle_t *p_hdr = (memm_handle_t *)hdl;
    memm_node_handle_t *p_cur_data_block = &((memm_node_handle_t *)p)[-1];
    size_t cur_data_block_size = p_cur_data_block->space_size - _MEMM_BLOCK_MANAGER_SPACE;
    void *ret;

    /* 使空间大小按要求对齐 */
    newsize = (newsize + sizeof(size_t) - 1) / sizeof(size_t) * sizeof(size_t);

    if (newsize == cur_data_block_size)
    {
        return p;
    }
    else if (newsize < cur_data_block_size)
    {
        /* 合并后一个空闲块 */
        size_t space_size = p_cur_data_block->space_size;
        memm_node_handle_t *p_next_free_block = (memm_node_handle_t *)&((uint8_t *)p_cur_data_block)[p_cur_data_block->space_size];
        if ((size_t)p_next_free_block < (size_t)_MEMM_GET_POINTER(p_hdr->end)) // 当前内存块不是在最顶端
        {
            if (p_next_free_block->next != _MEMM_DATA_VALID) // 与后一个相邻的块是空闲块
            {
                /* 更新信息 */
                space_size += p_next_free_block->space_size;

                /* 删除空闲块链接 */
                _memm_link_free_remove(p_hdr, p_next_free_block);
            }
        }

        /* 重新链接空闲块 */
        _memm_link_free_insert(p_hdr, p_cur_data_block, space_size);

        _memm_link_free_remove(p_hdr, p_cur_data_block); /* 从空闲链移出 */
        return _memm_link_alloc(p_hdr, p_cur_data_block, p_cur_data_block->space_size, newsize + _MEMM_BLOCK_MANAGER_SPACE, 0);
    }
    else
    {
        memm_node_handle_t *p_next_free_block = (memm_node_handle_t *)&((uint8_t *)p_cur_data_block)[p_cur_data_block->space_size];
        size_t expand_size = cur_data_block_size;

        /* 优先判断后面的内存直接进行扩充后的容量 expand_size ，以避免可能存在的大量的数据复制 */
        if ((size_t)p_next_free_block < (size_t)_MEMM_GET_POINTER(p_hdr->end) // 当前内存块不是在最顶端
            && p_next_free_block->next != _MEMM_DATA_VALID                    // 与后一个相邻的块是空闲块
        )
        {
            expand_size += p_next_free_block->space_size;
        }

        if (expand_size < newsize) // 不能直接进行扩充
        {
            memm_node_handle_t *p_prev_free_block = p_cur_data_block;

            if ((size_t)p_cur_data_block > (size_t)_MEMM_GET_POINTER(p_hdr->start)) // 当前内存块不是在最底端
            {
                memm_tail_active_t *p_prev_tail_struce_data = ((memm_tail_active_t *)&((uint8_t *)p_cur_data_block)[-sizeof(memm_tail_active_t)]);

                if (p_prev_tail_struce_data->prev != _MEMM_DATA_VALID) // 与前一个相邻的块是空闲块
                {
                    memm_tail_free_t *p_prev_tail_struct_free = ((memm_tail_free_t *)&((uint8_t *)p_cur_data_block)[-sizeof(memm_tail_free_t)]);
                    p_prev_free_block = _MEMM_GET_POINTER(p_prev_tail_struct_free->self);

                    /* 更新信息 */
                    expand_size += p_prev_free_block->space_size;
                }
            }

            /* 判断是否有能满足扩充的空闲块 */
            if (expand_size >= newsize)
            {
                // 当内存释放后，由数据结构变成空闲结果，备份空闲结构多出来的部分的数据
                void **data_addr1 = (void **)&((uint8_t *)p)[cur_data_block_size - sizeof(memm_node_handle_t *)];
                void *data_bak1 = *data_addr1;

                // 当内存申请后，新的数据结构的结尾可能会覆盖原数据，备份被覆盖前的部分的数据（包含可能紧接着的空闲区的数据结构）
                void **data_addr2 = (void **)&((uint8_t *)&p_prev_free_block[1])[newsize];
                void *data_bak2[(sizeof(memm_node_handle_t *) + sizeof(memm_node_handle_t)) / sizeof(memm_node_handle_t *)];

                void **new_data_addr;
                signed new_data_dev;
                size_t i;

                for (i = 0; i < sizeof(data_bak2) / sizeof(data_bak2[0]); i++)
                {
                    data_bak2[i] = data_addr2[i];
                }

                /* 先释放原内存，再申请新内存 */
                memm_free(hdl, p);
                ret = _memm_malloc(hdl, newsize, 0);
                memcpy(ret, p, cur_data_block_size);

                new_data_dev = (size_t)ret - (size_t)p;
                new_data_addr = (void **)&((uint8_t *)data_addr1)[new_data_dev];
                *new_data_addr = data_bak1;

                for (i = 0; i < sizeof(data_bak2) / sizeof(data_bak2[0]); i++)
                {
                    if ((size_t)&data_addr2[i] >= (size_t)p &&
                        (size_t)&data_addr2[i] < (size_t)p + cur_data_block_size)
                    {
                        new_data_addr = (void **)&((uint8_t *)&data_addr2[i])[new_data_dev];
                        *new_data_addr = data_bak2[i];
                    }
                }
            }
            else
            {
                /* 先申请新内存 */
                ret = _memm_malloc(hdl, newsize, 0);
                if (ret == NULL)
                {
                    return NULL;
                }

                memcpy(ret, p, cur_data_block_size);

                memm_free(hdl, p);
            }

            return ret;
        }
        else // 可直接进行扩充
        {
            if (expand_size > cur_data_block_size) // 后面的是可进行扩充的空闲内存
            {
                /* 删除空闲块链接 */
                _memm_link_free_remove(p_hdr, p_next_free_block);
            }

            /* 申请内存 */
            return _memm_link_alloc(p_hdr, p_cur_data_block, expand_size + _MEMM_BLOCK_MANAGER_SPACE, newsize + _MEMM_BLOCK_MANAGER_SPACE, 0);
        }
    }
}

static void *_memm_link_alloc(memm_handle_t *p_hdr, memm_node_handle_t *p_free_block, size_t block_space, size_t alloc_space, signed tail)
{
    /* 确认剩余空间有效(调试用) */
    if (block_space < alloc_space)
    {
        return NULL;
    }

    /* 根据剩余空闲大小，分割或合并剩余空间 */
    if (block_space >= alloc_space + sizeof(memm_node_handle_t) + sizeof(memm_tail_free_t)) // 取出后剩余的空间可以分出来再用
    {
        /* 把剩余空间插入到新空闲链中 */
        if (tail == 0)
        {
            memm_node_handle_t *p_new_free_block = (memm_node_handle_t *)&((uint8_t *)p_free_block)[alloc_space];
            _memm_link_free_insert(p_hdr, p_new_free_block, block_space - alloc_space);
        }
        else
        {
            memm_node_handle_t *p_new_free_block = p_free_block;
            p_free_block = (memm_node_handle_t *)&((uint8_t *)p_free_block)[block_space - alloc_space];
            _memm_link_free_insert(p_hdr, p_new_free_block, block_space - alloc_space);
        }
    }
    else // 剩余的空间无法再用
    {
        alloc_space = block_space;
    }

    /* 标记为有效 */
    memm_node_handle_t *p_data_block = p_free_block;
    memm_tail_active_t *p_data_block_tail = _MEMM_BLOCK_DATA_TAIL_Struct(p_data_block, alloc_space);
    p_data_block->space_size = alloc_space;
    p_data_block->next = _MEMM_DATA_VALID;
    p_data_block_tail->prev = _MEMM_DATA_VALID;

    return &p_data_block[1];
}

static void _memm_link_free_insert(memm_handle_t *p_hdr, memm_node_handle_t *p_free_block, size_t space_size)
{
    /* 通过 space_size 找到对应的表项 */
    size_t bit_mask_free = _MEMM_FREE_TAB_NUMS - _cpu_clz(space_size);
    memm_node_t *pp_free_hdr = &p_hdr->free_node[bit_mask_free - 1];
    memm_tail_free_t *p_free_block_tail = _MEMM_BLOCK_FREE_TAIL_Struct(p_free_block, space_size);

    /* 记录空间大小和本块位置 */
    p_free_block->space_size = space_size;
    p_free_block_tail->self = _MEMM_GET_DEV_VALUE(p_free_block);

    /* 插入到链尾 */
    if (*(void **)pp_free_hdr == NULL) // 首个链
    {
        p_free_block->next = _MEMM_GET_DEV_VALUE(p_free_block);
        p_free_block_tail->prev = _MEMM_GET_DEV_VALUE(p_free_block);
    }
    else
    {
        memm_node_handle_t *p_free_hdr = _MEMM_GET_POINTER(*pp_free_hdr);
        memm_tail_free_t *p_free_hdr_tail = _MEMM_BLOCK_FREE_TAIL_Struct(p_free_hdr, p_free_hdr->space_size);
        memm_node_handle_t *p_tail_block = _MEMM_GET_POINTER(p_free_hdr_tail->prev);

        p_free_block->next = _MEMM_GET_DEV_VALUE(p_free_hdr);
        p_free_block_tail->prev = _MEMM_GET_DEV_VALUE(p_tail_block);
        p_tail_block->next = _MEMM_GET_DEV_VALUE(p_free_block);
        p_free_hdr_tail->prev = _MEMM_GET_DEV_VALUE(p_free_block);
    }

    /* 更新链头 */
    *pp_free_hdr = _MEMM_GET_DEV_VALUE(p_free_block);

    /* 记录表项 */
    p_hdr->bm_free |= (1 << (_MEMM_FREE_TAB_NUMS - bit_mask_free));

    /* 使用记录 */
    p_hdr->free_total += space_size - _MEMM_BLOCK_MANAGER_SPACE;
}

static void _memm_link_free_remove(memm_handle_t *p_hdr, memm_node_handle_t *p_free_block)
{
    /* 通过 data_size 找到对应的表项 */
    size_t bit_mask_free = _MEMM_FREE_TAB_NUMS - _cpu_clz(p_free_block->space_size);
    memm_node_t *pp_free_hdr = &p_hdr->free_node[bit_mask_free - 1];
    memm_tail_free_t *p_free_block_tail = _MEMM_BLOCK_FREE_TAIL_Struct(p_free_block, p_free_block->space_size);

    memm_node_handle_t *p_next_block;
    memm_tail_free_t *p_next_block_tail;
    memm_node_handle_t *p_tail_block;

    p_hdr->free_total -= p_free_block->space_size - _MEMM_BLOCK_MANAGER_SPACE;

    if (_MEMM_GET_POINTER(*pp_free_hdr) == p_free_block) // 当前链头所指向
    {
        *pp_free_hdr = p_free_block->next;
        if (_MEMM_GET_POINTER(*pp_free_hdr) == p_free_block) // 已是最后一个链项
        {
            *(void **)pp_free_hdr = NULL;
            p_hdr->bm_free &= ~(1 << (_MEMM_FREE_TAB_NUMS - bit_mask_free));
            return;
        }
    }

    p_next_block = _MEMM_GET_POINTER(p_free_block->next);
    p_next_block_tail = _MEMM_BLOCK_FREE_TAIL_Struct(p_next_block, p_next_block->space_size);
    p_tail_block = _MEMM_GET_POINTER(p_free_block_tail->prev);

    p_tail_block->next = _MEMM_GET_DEV_VALUE(p_next_block);
    p_next_block_tail->prev = p_free_block_tail->prev;
}

#endif /* #if defined(CONFIG_MEMM_TYPE) && (CONFIG_MEMM_TYPE == 2) */
